package com.peanutplan.blog.controller.admin;



import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.bulk.BulkResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import com.peanutplan.blog.controller.BaseController;
import com.peanutplan.blog.dto.LogActions;
import com.peanutplan.blog.dto.Types;
import com.peanutplan.blog.exception.TipException;
import com.peanutplan.blog.model.AjaxResult;
import com.peanutplan.blog.model.bo.RestResponseBo;
import com.peanutplan.blog.model.vo.ContentEsVo;
import com.peanutplan.blog.model.vo.ContentVo;
import com.peanutplan.blog.model.vo.ContentVoExample;
import com.peanutplan.blog.model.vo.MetaVo;
import com.peanutplan.blog.model.vo.UserVo;
import com.peanutplan.blog.service.IContentService;
import com.peanutplan.blog.service.ILogService;
import com.peanutplan.blog.service.IMetaService;
import com.peanutplan.blog.utils.DefaultCover;
import com.peanutplan.blog.utils.ElasticSearchUtils;

/**
 * Created by 13 on 2017/2/21.
 */
@Controller
@RequestMapping("/admin/article")
@Transactional(rollbackFor = TipException.class)
public class ArticleController extends BaseController {

    private static final Logger LOGGER = LoggerFactory.getLogger(ArticleController.class);

    @Resource
    private IContentService contentsService;

    @Resource
    private IMetaService metasService;

    @Resource
    private ILogService logService;
    
    @Resource
    private DefaultCover defaultCover;

    /**
     * 全量同步到es
     * @return
     */
    @GetMapping(value = {"tongbu"})
    @ResponseBody
    public AjaxResult tongbu() {
    	try {
    		long start = System.currentTimeMillis();
    		String index = "article";
    		//先删除
    		long updated = ElasticSearchUtils.clearIndex(index);
    		LOGGER.info("删除索引["+index+"]共"+updated+"条数据");
    		
			int pageSize = 200;
			PageInfo<ContentVo> contentsPaginator = contentsService.getArticlesWithpage(null,1,pageSize);
			LOGGER.info("需同步数据共{}条，分页进行同步，每页{}条数据共{}页", contentsPaginator.getTotal(), pageSize, contentsPaginator.getPages());
			LOGGER.info("开始同步第{}页", 1);
			List<ContentEsVo> page1 = new ArrayList<>(contentsPaginator.getList().size());
			for(int i=0; i<contentsPaginator.getList().size(); i++) {
				ContentVo article = contentsPaginator.getList().get(i);
				ContentEsVo entity = new ContentEsVo(article);
				page1.add(entity);
			}
			BulkResponse r = ElasticSearchUtils.bulkAdd(index, page1, null);
			if(r.hasFailures()) {
				LOGGER.error("第{}页同步失败：{}", 1, JSON.toJSONString(r));
			}
			
			if(contentsPaginator.getPages()>1) {
				for(int page=2; page<=contentsPaginator.getPages(); page++) {
					LOGGER.info("开始同步第{}页", page);
					PageInfo<ContentVo> getPage = contentsService.getArticlesWithpage(null,page,pageSize);
					List<ContentEsVo> pageData = new ArrayList<>(getPage.getList().size());
					
					for(int i=0; i<getPage.getList().size(); i++) {
			    		ContentVo article = getPage.getList().get(i);
			    		ContentEsVo entity = new ContentEsVo(article);
			    		pageData.add(entity);
			    	}
					BulkResponse br = ElasticSearchUtils.bulkAdd(index, pageData, "cid");
					
					if(br.hasFailures()) {
						LOGGER.error("第{}页同步失败：{}", page, JSON.toJSONString(br));
					}
				}
			}
			
			long end = System.currentTimeMillis();
			DecimalFormat df2 = new DecimalFormat("###.0");
			String msg = "同步成功，用时"+df2.format(new Double(end-start)/1000/60)+"分钟";
			LOGGER.info(msg);
			return AjaxResult.success(msg);
		} catch (Exception e) {
			e.printStackTrace();
			AjaxResult error = AjaxResult.error(e.getMessage()==null?e.getCause().toString():e.getMessage());
			return error;
		}
    	
    }/**
     * 更新默认图片
     * @return
     */
    @GetMapping(value = {"refreshDefaultCover"})
    @ResponseBody
    public AjaxResult refreshDefaultCover() {
    	try {
    		defaultCover.run("");
			String msg = "默认文章封面刷新成功";
			LOGGER.info(msg);
			return AjaxResult.success(msg);
		} catch (Exception e) {
			e.printStackTrace();
			return AjaxResult.error(e.getMessage());
		}
    	
    }
    
    /**
     * 文章列表
     * @param page
     * @param limit
     * @param request
     * @return
     */
    @GetMapping(value = "")
    public String index(@RequestParam(value = "page", defaultValue = "1") int page,
                        @RequestParam(value = "limit", defaultValue = "10") int limit, @RequestParam(value = "category", defaultValue = "")String category, HttpServletRequest request) {
    	
    	List<MetaVo> categories = metasService.getMetas(Types.CATEGORY.getType());
    	request.setAttribute("categories", categories);
    	
    	ContentVoExample contentVoExample = new ContentVoExample();
        contentVoExample.setOrderByClause("created desc");
        ContentVoExample.Criteria criteria = contentVoExample.createCriteria();
        
        criteria.andTypeEqualTo(Types.ARTICLE.getType());
        if(StringUtils.isNoneBlank(category)) {
        	criteria.andCategoriesLike("%"+category+"%");
        }
        request.setAttribute("category", category);
        
        contentVoExample.setOrderByClause("allow_ping desc, created desc");
        
        PageInfo<ContentVo> contentsPaginator = contentsService.getArticlesWithpage(contentVoExample,page,limit);
        request.setAttribute("articles", contentsPaginator);
        return "admin/article_list";
    }

    /**
     * 文章发表
     * @param request
     * @return
     */
    @GetMapping(value = "/publish")
    public String newArticle(HttpServletRequest request) {
        List<MetaVo> categories = metasService.getMetas(Types.CATEGORY.getType());
        request.setAttribute("categories", categories);
        return "admin/article_edit";
    }

    /**
     * 文章编辑
     * @param cid
     * @param request
     * @return
     */
    @GetMapping(value = "/{cid}")
    public String editArticle(@PathVariable String cid, HttpServletRequest request) {
        ContentVo contents = contentsService.getContents(cid);
        request.setAttribute("contents", contents);
        List<MetaVo> categories = metasService.getMetas(Types.CATEGORY.getType());
        request.setAttribute("categories", categories);
        request.setAttribute("active", "article");
        return "admin/article_edit";
    }

    /**
     * 文章发表
     * @param contents
     * @param request
     * @return
     */
    @PostMapping(value = "/publish")
    @ResponseBody
    @Transactional(rollbackFor = TipException.class)
    public RestResponseBo<?> publishArticle(ContentVo contents, HttpServletRequest request) {
        UserVo users = this.user(request);
        contents.setAuthorId(users.getUid());
        contents.setType(Types.ARTICLE.getType());
        
        if(StringUtils.isBlank(contents.getCover())) {
//        	int radom = getRandom(1, 4);
//        	if(radom%2==0) {
//        		contents.setCover("/yqq/images/default_"+radom+".jpg");
//        	}else {
//        		contents.setCover("/yqq/images/b0"+getRandom(1, 5)+".jpg");
//        	}
        	
        	int random = getRandom(1, DefaultCover.DEFAULT_ARTICLE_COVER_MAP.size());
        	contents.setCover(DefaultCover.DEFAULT_ARTICLE_COVER_MAP.get(new Integer(random)));
        }
        
        if (StringUtils.isBlank(contents.getCategories())) {
            contents.setCategories("默认分类");
        }
        try {
            contentsService.publish(contents);
        } catch (Exception e) {
            String msg = "文章发布失败";
            if (e instanceof TipException) {
                msg = e.getMessage();
            } else {
                LOGGER.error(msg, e);
            }
            return RestResponseBo.fail(msg);
        }
        return RestResponseBo.ok();
    }
    
    public static int getRandom(int min, int max){
        Random random = new Random();
        int s = random.nextInt(max) % (max - min + 1) + min;
        return s;

    }

    /**
     * 文章更新
     * @param contents
     * @param request
     * @return
     */
    @PostMapping(value = "/modify")
    @ResponseBody
    @Transactional(rollbackFor = TipException.class)
    public RestResponseBo<?> modifyArticle(ContentVo contents,HttpServletRequest request) {
        UserVo users = this.user(request);
        contents.setAuthorId(users.getUid());
        contents.setType(Types.ARTICLE.getType());
        if(StringUtils.isBlank(contents.getCover())) {
        	int radom = getRandom(1, 4);
        	if(radom%2==0) {
        		contents.setCover("/yqq/images/"+radom+".jpg");
        	}else {
        		contents.setCover("/yqq/images/b0"+getRandom(1, 5)+".jpg");
        	}
        }
        try {
            contentsService.updateArticle(contents);
        } catch (Exception e) {
        	e.printStackTrace();
            String msg = "文章编辑失败";
            if (e instanceof TipException) {
                msg = e.getMessage();
            } else {
                LOGGER.error(msg, e);
            }
            return RestResponseBo.fail(msg);
        }
        return RestResponseBo.ok();
    }

    /**
     * 删除文章
     * @param cid
     * @param request
     * @return
     */
    @RequestMapping(value = "/delete")
    @ResponseBody
    @Transactional(rollbackFor = TipException.class)
    public RestResponseBo<?> delete(@RequestParam int cid, HttpServletRequest request) {
        try {
            contentsService.deleteByCid(cid);
            logService.insertLog(LogActions.DEL_ARTICLE.getAction(), cid+"", request.getRemoteAddr(), this.getUid(request));
        } catch (Exception e) {
            String msg = "文章删除失败";
            if (e instanceof TipException) {
                msg = e.getMessage();
            } else {
                LOGGER.error(msg, e);
            }
            return RestResponseBo.fail(msg);
        }
        return RestResponseBo.ok();
    }
}
